<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Draw polyline | Sample | ArcGIS API for JavaScript 4.16</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.16/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.16/"></script>

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/views/draw/Draw",
            "esri/Graphic",
            "esri/geometry/geometryEngine"
        ], function(Map, MapView, Draw, Graphic, geometryEngine) {
            const map = new Map({
                basemap: "gray"
            });

            const view = new MapView({
                container: "viewDiv",
                map: map,
                zoom: 16,
                center: [18.06, 59.34]
            });

            // 添加绘制工具的按钮
            view.ui.add("line-button", "top-left");
            // view.ui.add(toggle, "top-right");
            // view.ui.move(["zoom", toggle], "bottom-left");
            // view.ui.empty("bottom-left");
            // view.ui.remove("compass");
            // view.ui.components = ["attribution"];

            const draw = new Draw({
                view: view
            });

            // 绘制折线按钮
            document.getElementById("line-button").onclick = function() {
                //从视图中删除所有图形
                view.graphics.removeAll();

                // 创建并返回PolyLineDrawAction的实例
                const action = draw.create("polyline");

                // 聚焦视图以激活用于绘制草图的键盘快捷键
                view.focus();

                // 侦听polylineDrawAction事件，以便在视图上绘制线条时向用户提供直观的视觉反馈
                action.on(
                    [
                        "vertex-add",
                        "vertex-remove",
                        "cursor-update",
                        "redo",
                        "undo",
                        "draw-complete"
                    ],
                    updateVertices
                );
            };

            // 检查最后一个顶点是否使线相交
            function updateVertices(event) {
                // 根据返回的顶点创建折线
                if (event.vertices.length > 1) {
                    const result = createGraphic(event);

                    // 如果最后一个顶点使线相交，防止事件触发
                    if (result.selfIntersects) {
                        event.preventDefault();
                    }
                }
            }

            // 创建一个新图形，以显示在视图上绘制的折线
            function createGraphic(event) {
                const vertices = event.vertices;
                view.graphics.removeAll();

                // 代表正在绘制的折线的图形
                const graphic = new Graphic({
                    geometry: {
                        type: "polyline",
                        paths: vertices,
                        spatialReference: view.spatialReference
                    },
                    symbol: {
                        type: "simple-line", // autocasts as new SimpleFillSymbol
                        color: [4, 90, 141],
                        width: 4,
                        cap: "round",
                        join: "round"
                    }
                });

                // 检查折线是否相交。
                const intersectingSegment = getIntersectingSegment(graphic.geometry);

                // 为相交线段添加新图形
                if (intersectingSegment) {
                    view.graphics.addMany([graphic, intersectingSegment]);
                }
                // 如果没有交集，只需添加代表折线的图形
                else {
                    view.graphics.add(graphic);
                }

                // 返回intersectingSegment
                return {
                    selfIntersects: intersectingSegment
                };
            }

            // 检查线是否相交的函数
            function isSelfIntersecting(polyline) {
                if (polyline.paths[0].length < 3) {
                    return false;
                }
                const line = polyline.clone();

                //从绘制的折线中获取最后一个线段
                const lastSegment = getLastSegment(polyline);
                line.removePoint(0, line.paths[0].length - 1);

                // 如果线相交，则返回true，否则返回false
                return geometryEngine.crosses(lastSegment, line);
            }

            //检查线是否相交。如果是，请更改最后一段的符号，以向用户提供视觉反馈
            function getIntersectingSegment(polyline) {
                if (isSelfIntersecting(polyline)) {
                    return new Graphic({
                        geometry: getLastSegment(polyline),
                        symbol: {
                            type: "simple-line", // autocasts as new SimpleLineSymbol
                            style: "short-dot",
                            width: 3.5,
                            color: "yellow"
                        }
                    });
                }
                return null;
            }

            // 获取绘制的折线的最后一段
            function getLastSegment(polyline) {
                const line = polyline.clone();
                const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
                const existingLineFinalPoint = line.getPoint(
                    0,
                    line.paths[0].length - 1
                );

                return {
                    type: "polyline",
                    spatialReference: view.spatialReference,
                    hasZ: false,
                    paths: [
                        [
                            [existingLineFinalPoint.x, existingLineFinalPoint.y],
                            [lastXYPoint.x, lastXYPoint.y]
                        ]
                    ]
                };
            }
        });
    </script>
</head>

<body>
    <div id="viewDiv">
        <div id="line-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polyline">
            <span class="esri-icon-polyline"></span>
        </div>
    </div>
</body>

</html>